<?php
declare (strict_types=1);

namespace app\common\service;


use app\common\model\DidImage;
use app\common\model\DidTalk;
use app\common\model\User;
use app\common\model\UserDigitalHuman;
use app\common\model\VoiceLab;
use GuzzleHttp\Client;
use think\facade\Config;
use think\facade\Filesystem;
use think\file\UploadedFile;

class DidService extends CommonBaseService
{

    protected array $config;
    protected array $options;
    protected Client $client;

    public function __construct()
    {
        $this->config = Config::get('tripartite_setting.api_config');
        $this->options = [
            'headers'=>[
                'Authorization'=>$this->config['did_apikey'],
                'Accept' => '*/*',
                'Connection' => 'keep-alive',
            ],
            'verify' => false
        ];
        $this->client = new Client(['base_uri' => $this->config['did_host']]);
    }

    /**
     * @param UserDigitalHuman $udh
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function addImage2(UserDigitalHuman $udh): bool{

        $image = DidImage::where(['user_id'=>$udh->user_id,'user_dh_id'=>$udh->id])->find();
        if (empty($image->img_id)){
            $this->options['multipart'][] = [
                'name' => 'image',
                'contents' => fopen(app()->getRootPath()."public".$image['url'], 'r'),
                'filename' => pathinfo($image['url'])['basename'],
                'headers'  => ['Content-Type' => '<Content-type header>']
            ];
            $content = $this->client->post('images', $this->options)
                ->getBody()->getContents();

            $data = json_decode($content,true);

            //将上传后的数据保存到数据库，并跟用户关联起来
            $image->did_url = $data['url'];
            $image->img_id = $data['id'];
            if (!$image->save()){
                return false;
            }

            //图片上传完成后，创建talk
            unset($this->options['multipart']);
        }

        $this->addTalk([
            'source_url'=>$image->did_url,
            'user_dh_id'=>$image->user_dh_id,
            'text'      =>'hello,world!',
            'user_id'   =>$image->user_id]
        );

        $udh->create_status = UserDigitalHuman::CREATE_STATUS[1];
        return $udh->save();
    }

    /**
     * @param UploadedFile $image
     * @param User $user
     * @return array
     */
    public function addImage(UploadedFile $image,User $user): array {

        $this->options['multipart'][] = [
            'name' => 'image',
            'contents' => fopen($image->getPathname(), 'r'),
            'filename' => $image->getOriginalName(),
            'headers'  => ['Content-Type' => '<Content-type header>']
        ];
        $content = $this->client->post('images', $this->options)
            ->getBody()->getContents();
        $data = json_decode($content,true);

        $name = Filesystem::putFile('did_images', $image);
        $config_url = config('filesystem.disks.public.url');
        $url = $config_url . '/' . $name;
        $url = str_replace("\\", '/', $url);

        //将上传后的数据保存到数据库，并跟用户关联起来
        $im = new DidImage();
        $im->user_id = $user->id;
        $im->url = $url;
        $im->did_url = $data['url'];
        $im->img_id = $data['id'];
        $im->save();
        return $im->toArray();
    }

    /**
     * @param array $param
     * @param int $page
     * @param int $limit
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getImages(array $param,int $page,int $limit):array {
        $m = DidImage::where('user_id',$param['user_id']);
        $count = $m->count();
        $list = [];
        if (!empty($count)){
            $list = $m
                ->field("id,url,did_url,img_id,create_time")
                ->page($page, $limit)
                ->select()
                ->toArray();
        }
        return ['count'=>$count,'list'=>$list];
    }


    /**
     * @param array $param
     * @return bool
     * @throws \Exception
     */
    public function delImage(array $param): bool {

        $img = DidImage::where(['id'=>$param['id']])->findOrEmpty();
        if ($img->isEmpty()){
            throw new \Exception('数据未找到！');
        }
        if ($img->user_id != $param['user_id']){
            throw new \Exception("该数据不是您的！");
        }
        if ($img->delete()){
            //$content = $this->client->delete('/images/'.$img->img_id,$this->options)->getBody()->getContents();
        }

        return true;
    }


    /**
     * @param array $param
     * @return bool
     * @throws \Exception
     */
    public function delTalk(array $param): bool {

        $talk = DidTalk::where(['id'=>$param['id']])->findOrEmpty();
        if ($talk->isEmpty()){
            throw new \Exception('数据未找到！');
        }
        if ($talk->user_id != $param['user_id']){
            throw new \Exception("该数据不是您的！");
        }

        if ($talk->delete()){
            //$content = $this->client->delete('/talk/'.$img->talk_id,$this->options)->getBody()->getContents();
        }

        return true;
    }

    /**
     * @param array $param
     * @return array
     */
    public function addTalk(array $param): array {
        $this->options['json']  = [
                'source_url'=>$param['source_url'],
                'script'=>[
                            'type'=>'text',
                            'input'=>$param['text'],
                        ],
                        'config'=>[
                            'align_driver'=>false,
                            'stitch'=>false,
                        ]
                ];
        $content =  $this->client
            ->post('talks', $this->options)
            ->getBody()->getContents();
        $data = json_decode($content,true);

        //将上传后的数据保存到数据库，并跟用户关联起来
        $m              = new DidTalk();
        $m->user_id     = $param['user_id'];
        $m->user_dh_id  = $param['user_dh_id'];
        $m->talk_id     = $data['id'];
        $m->save();
        return $data;
    }

    /**
     * @param int $id
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getTalkById(int $id):array {
        $talk = DidTalk::where('id',$id)
        ->field("id,user_id,did_status,result_url,talk_id,source_url,config,create_time,update_time")
        ->findOrEmpty();
        if (!$talk->isEmpty() && empty($talk->did_status)){

//            var_dump($talk->did_status);die;
            $response = $this->client->get('/talks/'.$talk->talk_id, $this->options);

            $res_data = json_decode($response->getBody()->getContents(),true);

//            var_dump($res_data);die;
            if ($res_data['status'] == 'done'){
                $talk->config = json_encode($res_data['config']);
                $talk->result_url = $res_data['result_url'];
            }else{
                $talk->config = json_encode($res_data['error']);
            }
            $talk->did_status = $res_data['status'];
            $talk->source_url = $res_data['source_url'];
            $talk->save();
        }
        return $talk->toArray();
    }

    /**
     * @param array $param
     * @param int $page
     * @param int $limit
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getTalks(array $param,int $page,int $limit):array {
        $m = DidTalk::where('user_id',$param['user_id']);
        $count = $m->count();
        $list = [];
        if (!empty($count)){
            $list = $m
                ->field("id,result_url,talk_id,source_url,config,create_time,did_status")
                ->page($page, $limit)
                ->select()
                ->toArray();
        }
        return ['count'=>$count,'list'=>$list];
    }

    /**
     * @param array $param
     * @param int $limit
     * @return array
     */
    public function getDidTalks(array $param,int $limit): array {
        $query = ['limit'=>$limit];

        if (!empty($param['token'])){
            $query['token'] = $param['token'];
        }

        $this->options['query'] = $query;
        $response = $this->client->get('/talks', $this->options);

        $data = json_decode($response->getBody()->getContents(),true);
        $insert_data = [];
        foreach ($data['talks'] as &$talk){
            unset($talk['user']);
            $insert_data[] = [
                'user_id'=>$param['user_id'],
                'talk_id'=>$talk['id'],
            ];
        }

        $m = new DidTalk();
        $m->saveAll($insert_data);
        return $data;
    }
}